require "ISUI/ISPanelJoypad"

ESR = ESR or {}
ESR.Rankings = ESR.Rankings or {}
ESR.Rankings.Client = ESR.Rankings.Client or {}
ESR.Rankings.Client.data = ESR.Rankings.Client.data or {}
ESR.Rankings.Client.Commands = ESR.Rankings.Client.Commands or {}

local StockTexture = {"risky_investment_spiffo", "risky_investment_gas2go", "risky_investment_fossil", "risky_investment_gigamart", "risky_investment_poc", "risky_investment_mccoy",
                      "risky_investment_valutech", "risky_investment_pizzawhirled", "risky_investment_tacodelpancho"}


local investmentWindow = {}

Events.OnServerCommand.Add(function(module, command, arguments)
    getPlayer():Say(""..module.." "..command)
    print("==================Client==================OnServerCommand===================")
    print(arguments)
    if module == ESR.Rankings.Shared.MODULE_NAME then
        if (command == 'DataFromServer' or command == 'StockDataFromServer') then
            ESR.Rankings.Client.Commands[command](arguments);
        else
            print("Command mismatch:", command)
        end
    else
        print("Module mismatch:", module)
    end
end);

local function OnGameStart()
    print("==========OnGameStart1===========sendClientCommand==========CreatePlayer ")
    local player = getPlayer()
    print("==========OnGameStart2===========sendClientCommand==========CreatePlayer "..player:getUsername())
    sendClientCommand(player, ESR.Rankings.Shared.MODULE_NAME, "CreatePlayer", { player:getUsername() })
end

local function OnCharacterDeath(_player)
    local player = getPlayer() or getSpecificPlayer(_player);
    if (player) then
        if (investmentWindow[0] ~= nil and investmentWindow[0]:getIsVisible()) then
            investmentWindow[0]:close()
        end
    end
end


ExaStockRankingTradeUI = ISCollapsableWindowJoypad:derive("ExaStockRankingTradeUI")

function ExaStockRankingTradeUI:new(x, y, width, height, character)
    local o = {}
    o = ISCollapsableWindowJoypad:new(x, y, width, height)
    print("=====ExaStockRankingTradeUI:new=============================")
    setmetatable(o, self)
    self.__index = self
    o.character = character
    o.buttons = {}

    return o
end

function ExaStockRankingTradeUI:update()
    ISCollapsableWindowJoypad.update(self)

    if self and self:getIsVisible() then
        if (self.character:getPrimaryHandType() ~= "PDA" and self.character:getSecondaryHandType() ~= "PDA") then
            self:close()
            return
        end
    end

    local clientModData = ESR.Rankings.Client.data
    for i = 1, #self.buttons, 1 do
        if ((getGameTime():getHour() >= 0 and getGameTime():getHour() <= 7)
                or (getGameTime():getHour() >= 22 and getGameTime():getHour() <= 24)) then
            -- Buy Check
            if (self.character:getModData().fund >= clientModData.stock[i]) then
                self.buttons[i][1]:setEnable(true)
            else
                self.buttons[i][1]:setEnable(false)
            end

            -- Sell Check
            if (self.character:getModData().stock[i] ~= nil and self.character:getModData().stock[i] ~= 0) then
                self.buttons[i][2]:setEnable(true)
            else
                self.buttons[i][2]:setEnable(false)
            end
        else
            self.buttons[i][1]:setEnable(false)
            self.buttons[i][2]:setEnable(false)
        end
    end
end

-- 存款
function ExaStockRankingTradeUI:onDeposit(button, x, y)
    local moneyItems = self.character:getInventory():getItemsFromType("Money")
    self.character:getModData().fund = self.character:getModData().fund + moneyItems:size()

    sendClientCommand(player, ESR.Rankings.Shared.MODULE_NAME, "Deposit", { self.character:getUsername(), moneyItems:size() })

    for i = 0, moneyItems:size() - 1, 1 do
        self.character:getInventory():DoRemoveItem(moneyItems:get(i))
    end
end

function ExaStockRankingTradeUI:onWithdraw(button, x, y)
    -- local amountToAdd = math.ceil(self.character:getModData().fund * (100 - SandboxVars.Op_StockOutCost) / 100)
    self.character:getInventory():AddItems("Base.Money", self.character:getModData().fund)
    self.character:getModData().fund = 0
    sendClientCommand(player, ESR.Rankings.Shared.MODULE_NAME, "Withdraw", { self.character:getUsername()})
end

function ExaStockRankingTradeUI:prerender()
    ISCollapsableWindowJoypad.prerender(self)

    self:drawTexture(getTexture("Item_Money"), 15, 25, 1, 1, 1, 1)
    self:drawText(getText('IGUI_RISKY_INVEST_BALANCE') .. ": $" .. self.character:getModData().fund, 55, 25, 1, 1, 1, 1, UIFont.Medium)

    if ((getGameTime():getHour() >= 0 and getGameTime():getHour() <= 7 )
            or (getGameTime():getHour() >= 22 and getGameTime():getHour() <= 24 )) then
        -- 开启交易
        self:drawText(getText('IGUI_RISKY_INVEST_OPEN'), 55, 90, 0, 1, 0, 1, UIFont.Small)
    else
        -- 暂停交易
        self:drawText(getText('IGUI_RISKY_INVEST_CLOSE'), 55, 90, 1, 0, 0, 1, UIFont.Small)
    end

    local clientModData = ESR.Rankings.Client.data
    if clientModData.news[1] ~= nil then
        self:drawText(clientModData.news[1], 55, 125, 1, 1, 1, 1, UIFont.Small)
    else
        self:drawText("", 55, 125, 1, 1, 1, 1, UIFont.Small)
    end
    if clientModData.news[2] ~= nil then
        self:drawText(clientModData.news[2], 55, 145, 1, 1, 1, 1, UIFont.Small)
    else
        self:drawText("", 55, 145, 1, 1, 1, 1, UIFont.Small)
    end
    if clientModData.news[3] ~= nil then
        self:drawText(clientModData.news[3], 55, 165, 1, 1, 1, 1, UIFont.Small)
    else
        self:drawText("", 55, 165, 1, 1, 1, 1, UIFont.Small)
    end

    local entryHeight = 230

    for i = 1, math.min(#clientModData.stock, #StockTexture), 1 do
        local column = (i - 1) % 3 * 200
        local yestrdVal = clientModData.stockPrev[i]
        local currentVal = clientModData.stock[i]
        self:drawTextureScaled(getTexture("media/textures/" .. StockTexture[i] .. ".png"), 15 + column, entryHeight + 3, 38, 38, 1, 1, 1, 1)
        self:drawText(ESR.Rankings.Shared.StockName[i], 60 + column, entryHeight, 1, 1, 1, 1, UIFont.Small)

        self:drawText(getText('IGUI_RISKY_INVEST_PRICE') .. ": $" .. tostring(currentVal), 60 + column, entryHeight + 20, 1, 1, 1, 1, UIFont.Small)

        local changes = ((currentVal - yestrdVal) / yestrdVal) * 100
        if (changes < 0) then
            self:drawText(string.format("%.1f", changes) .. "%", 75 + column, entryHeight + 42, 1, 0, 0, 1, UIFont.Small)
            self:drawTextureScaled(getTexture("media/textures/risky_investment_decrease.png"), 60 + column, entryHeight + 48, 10, 10, 1, 1, 1, 1)
        else
            self:drawText(string.format("%.1f", changes) .. "%", 75 + column, entryHeight + 42, 0, 1, 0, 1, UIFont.Small)
            self:drawTextureScaled(getTexture("media/textures/risky_investment_increase.png"), 60 + column, entryHeight + 48, 10, 10, 1, 1, 1, 1)
        end

        local owned = self.character:getModData().stock[i]
        if (owned == nil) then
            owned = 0
        end

        self:drawText(getText('IGUI_RISKY_INVEST_OWNED') .. ": " .. tostring(owned), 60 + column, entryHeight + 70, 1, 1, 1, 1, UIFont.Small)
        self:drawText(getText('IGUI_RISKY_INVEST_OWNED') .. ": " .. tostring(owned) .. " / " .. tostring(SandboxVars.Op_StockMaxHoldings), 60 + column, entryHeight + 70, 1, 1, 1, 1, UIFont.Small)

        if (i % 3 == 0) then
            entryHeight = entryHeight + 150
        end
    end
end

function ExaStockRankingTradeUI:createChildren()
    ISCollapsableWindowJoypad.createChildren(self)

    local depositButton = ISButton:new(55, 60, 50, 25, getText('IGUI_RISKY_INVEST_DEPOSIT'), self, self.onDeposit)
    depositButton.borderColor.r = 0.0
    depositButton.borderColor.g = 255.0
    depositButton.borderColor.b = 0.0
    depositButton:initialise()
    depositButton:instantiate()
    self:addChild(depositButton)

    local withdrawButton = ISButton:new(115, 60, 50, 25, getText('IGUI_RISKY_INVEST_WITHDRAW'), self, self.onWithdraw)
    withdrawButton.borderColor.r = 255.0
    withdrawButton.borderColor.g = 0.0
    withdrawButton.borderColor.b = 0.0
    withdrawButton:initialise()
    withdrawButton:instantiate()
    self:addChild(withdrawButton)

    local entryHeight = 230
    local clientModData = ESR.Rankings.Client.data
    -- 计算当前总持仓数
    --local totalHoldings = 0
    --for j = 1, #modData.stock do
    --    totalHoldings = totalHoldings + (self.character:getModData().stock[j] or 0)
    --end

    for i = 1, #clientModData.stock, 1 do
        local column = (i - 1) % 3 * 200
        local buyButton = ISButton:new(60 + column, entryHeight + 95, 50, 25, getText('IGUI_RISKY_INVEST_BUY'), self, function()
            if (self.character:getModData().fund >= clientModData.stock[i]) then
                local currentHoldings = self.character:getModData().stock[i] or 0
                if currentHoldings >= SandboxVars.Op_StockMaxHoldings then
                    self.character:Say(getText('IGUI_RISKY_INVEST_MAXHOLDINGS',SandboxVars.Op_StockMaxHoldings))
                    return
                end
                if (self.character:getModData().stock[i] == nil) then
                    self.character:getModData().stock[i] = 0
                end

                sendClientCommand(player, ESR.Rankings.Shared.MODULE_NAME, "AddBuys", { self.character:getUsername(),clientModData.stock[i],i})
            else
                self.character:Say(getText('IGUI_RISKY_INVEST_NOTENOUGH'))
            end
        end)
        buyButton.borderColor.r = 0.0
        buyButton.borderColor.g = 255.0
        buyButton.borderColor.b = 0.0
        buyButton:initialise()
        buyButton:instantiate()
        self:addChild(buyButton)

        local sellButton = ISButton:new(120 + column, entryHeight + 95, 50, 25, getText('IGUI_RISKY_INVEST_SELL'), self, function()
            if (self.character:getModData().stock[i] ~= nil and self.character:getModData().stock[i] ~= 0) then

                local amountToAdd = math.ceil(clientModData.stock[i] * (100 - SandboxVars.Op_StockOutCost) / 100)
                local cost = clientModData.stock[i] - amountToAdd

                sendClientCommand(player, ESR.Rankings.Shared.MODULE_NAME, "AddSells", { self.character:getUsername(),amountToAdd,i})

                self.character:Say(getText("IGUI_RISKY_INVEST_SELL_RESULT",amountToAdd,cost))
            end
        end)
        sellButton.borderColor.r = 255.0
        sellButton.borderColor.g = 0.0
        sellButton.borderColor.b = 0.0
        sellButton:initialise()
        sellButton:instantiate()
        sellButton:setTooltip(getText("IGUI_RISKY_INVEST_SELL_DESC",SandboxVars.Op_StockOutCost))
        self:addChild(sellButton)

        table.insert(self.buttons, {buyButton, sellButton})

        if (i % 3 == 0) then
            entryHeight = entryHeight + 150
        end
    end
end

function ExaStockRankingTradeUI:close()
    self:setVisible(false)
    self:removeFromUIManager()
    investmentWindow[0] = nil
end

local function initExaStockRankingTradeWindow(character,item)
    if (investmentWindow[0] == nil or not investmentWindow[0]:getIsVisible()) then
        investmentWindow[0] = ExaStockRankingTradeUI:new(100, 100, 620, 745, character)
        investmentWindow[0]:setTitle(getText('IGUI_RISKY_INVEST_STOCKX'))
        investmentWindow[0]:addToUIManager()
        investmentWindow[0].resizable = false
        investmentWindow[0].collapsable = false
    else
        investmentWindow[0].itemBase = item
    end
end

local function OnEquipSecondary(character, item)
    if item and item:getType() == "PDA" and item:isEquipped() then
        initExaStockRankingTradeWindow(character, item)
    end
end

Events.OnEquipSecondary.Add(OnEquipSecondary)

local function OnEquipPrimary(character, item)
    if item and item:getType() == "PDA" and item:isEquipped() then
        initExaStockRankingTradeWindow(character, item)
    end
end

Events.OnEquipPrimary.Add(OnEquipPrimary)

local function createInventoryMenuEntry(_player, _context, _items)
    local resItems = {}
    local container = nil
    for i,v in ipairs(_items) do
        if not instanceof(v, "InventoryItem") then
            for _, it in ipairs(v.items) do
                resItems[it] = true
            end
            container = v.items[1]:getContainer()
        else
            resItems[v] = true
            container = v:getContainer()
        end
    end

    for v, _ in pairs(resItems) do
        if v:getType() == "PDA" and v:isEquipped() then
            _context:addOptionOnTop(getText('IGUI_RISKY_INVEST_BROWSE'), 0, function()
                initExaStockRankingTradeWindow(getSpecificPlayer(_player), v)
            end)
        end
    end
end

local function OnZombieDead(zombie)
    if (ZombRand(0, 1000) < 1) then
        zombie:getInventory():AddItem("RiskyInvestment.PDA")
    end
end

function ESR.Rankings.Client.Commands.DataFromServer(arguments)
    if arguments ~= nil then

        local currentPlayer = getPlayer()
        local currentUsername = currentPlayer:getUsername()

        for k, player in pairs(arguments) do
            if currentUsername == k then
                currentPlayer:getModData().stock = player.stock or {}
                currentPlayer:getModData().buys = player.buys or 0
                currentPlayer:getModData().sells = player.sells or 0
                currentPlayer:getModData().fund = player.fund or 0
            end
        end
    end
end

function ESR.Rankings.Client.Commands.StockDataFromServer(arguments)
    print("Rec=====================StockDataFromServer")
    if arguments ~= nil then
        if(arguments["numStock"]) then
            getPlayer():Say("numStock="..arguments["numStock"])
        end
        ESR.Rankings.Client.data = arguments["data"]
    end
end

function ESR.Rankings.Client.StockDataClient(module, command, arguments)
    if module == ESR.Rankings.Shared.MODULE_NAME then
        if (command == 'DataFromServer' or command == 'StockDataFromServer') then
            ESR.Rankings.Client.Commands[command](arguments);
        end
    end
end

Events.OnZombieDead.Add(OnZombieDead)
Events.OnGameStart.Add(OnGameStart)
-- Events.OnCreatePlayer.Add(OnCreatePlayer)
Events.OnCharacterDeath.Add(OnCharacterDeath)
Events.OnFillInventoryObjectContextMenu.Add(createInventoryMenuEntry)

